package io.gitee.gemini.utis;


import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Bean处理工具
 */
public class BeanUtil {


    private BeanUtil() {
    }

    /**
     * 对象转map
     *
     * @param bean    源对象
     * @param <T>     源对象类型
     * @param canNull value 可以为null
     * @return 根据源对象属性生成的map
     */
    public static <T> Map<String, Object> beanToMap(T bean, boolean canNull) {
        if (bean == null) {
            return null;
        }
        Class<?> clazz = bean.getClass();
        Field[] fields = ReflectUtil.getClassFields(clazz);
        Map<String, Object> result = new HashMap<>(fields.length);

        for (Field field : fields) {
            field.setAccessible(true);
            try {
                //过滤空值和静态对象
                if (Modifier.isStatic(field.getModifiers())) {
                    continue;
                }
                Object value = field.get(bean);
                if (value == null && !canNull) {
                    continue;
                }
                result.put(field.getName(), value);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return result;
    }


    /**
     * 对象转map 默认value为空不转换
     *
     * @param bean 原对象
     * @param <T>  原始类型
     * @return 对应实体转换的kv map
     */
    public static <T> Map<String, Object> beanToMap(T bean) {
        return beanToMap(bean, false);
    }


    /**
     * 复制对象同名属性
     *
     * @param target 目标对象
     * @param origin 原对象
     * @param <T>    目标对象类型
     * @param <O>    源对象类型
     */
    public static <T, O> void copyProperties(T origin, O target) {

        Field[] targetFields = ReflectUtil.getClassFields(target.getClass());

        Field[] originFields = ReflectUtil.getClassFields(origin.getClass());

        List<Field> fields = CollectionUtil.sameItem(originFields, targetFields);
        try {
            for (Field field : fields) {
                field.setAccessible(true);
                field.set(target, field.get(origin));
            }
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }


}
